/*
post data:
{"vip":"0","figureurl_qq_2":"http://q.qlogo.cn/qqapp/100445417/594D379DAE210D89A8C670C83A8038D6/100","ret":0,"figureurl":"http://qzapp.qlogo.cn/qzapp/100445417/594D379DAE210D89A8C670C83A8038D6/30","is_yellow_vip":"0","openid":"594D379DAE210D89A8C670C83A8038D6","gender":"\u7537","figureurl_1":"http://qzapp.qlogo.cn/qzapp/100445417/594D379DAE210D89A8C670C83A8038D6/50","nickname":"cool~doudou","figureurl_2":"http://qzapp.qlogo.cn/qzapp/100445417/594D379DAE210D89A8C670C83A8038D6/100","msg":"","figureurl_qq_1":"http://q.qlogo.cn/qqapp/100445417/594D379DAE210D89A8C670C83A8038D6/40","yellow_vip_level":"0"}

request:
http://127.0.0.1:9090/auth?sign=b789c55a49b8f1e573acac20943520d2

return data
{"message":"ok","ret":0,"data":{"uid":"594d379dae210d89a8c670c83a8038d6","nick":"cool~doudou","header":"http://qzapp.qlogo.cn/qzapp/100445417/594d379dae210d89a8c670c83a8038d6/100","gender":0,"babys":[],"source":"","babyrelations":{}}}
*/

package controllers

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io"
	"strings"
	"time"

	"github.com/astaxie/beego"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"

	"conf"
	"models"
	"models/gender"
	"models/response"
)

const authCodeKey = "tsbauthcodekey"

type AuthController struct {
	beego.Controller
}

func (this *AuthController) Post() {

	var result response.Response

	clientSignParam := this.GetString("sign")
	var postJson string
	postJson = fmt.Sprintf("%s", this.Ctx.RequestBody)
	fmt.Println(postJson)

	h := md5.New()
	ss := fmt.Sprintf("%s%s", authCodeKey, postJson)
	io.WriteString(h, ss)
	selfSignValue := fmt.Sprintf("%x", h.Sum(nil))

	if strings.EqualFold(clientSignParam, selfSignValue) {
		fmt.Println("sign ok")
	} else {
		result.Message = response.Info_Error_ParamError
		result.Ret = response.Code_Error_ParamError
		this.Ctx.WriteString(result.FormatJsonString())
		return
	}

	postJsonMap := map[string]interface{}{}
	error := json.Unmarshal([]byte(postJson), &postJsonMap)
	fmt.Println("%v", postJsonMap)
	if error != nil {
		result.Message = response.Info_Error_OperationFailed
		result.Ret = response.Code_Error_OperationFailed
		this.Ctx.WriteString(result.FormatJsonString())
		return
	}
	if len(postJsonMap) <= 0 {
		result.Message = response.Info_Error_ParamError
		result.Ret = response.Code_Error_ParamError
		this.Ctx.WriteString(result.FormatJsonString())
		return
	}

	openId := postJsonMap["openid"].(string)
	fmt.Println("openid:%s", openId)

	isExists, existsUser := isUserExistsDB(openId)
	if isExists {
		existsUser.Source = ""
		result.Message = "ok"
		result.Ret = response.Code_Success
		result.Data = existsUser
		this.Ctx.WriteString(result.FormatJsonString())
		return
	}

	fmt.Println("start insert db")
	var user models.User
	user.Nick = postJsonMap["nickname"].(string)
	user.Uid = openId
	user.Source = postJson
	user.CreateTime = time.Now()

	user.Gender = gender.Unknow

	if strings.EqualFold(postJsonMap["gender"].(string), "男") {
		user.Gender = gender.Male
	} else {
		user.Gender = gender.Female
	}
	user.Header = postJsonMap["figureurl_2"].(string)
	user.Id = bson.NewObjectId()
	fmt.Println("bson id:", user.Id)
	// 操作 db
	session, err := mgo.Dial(config.DataBaseIP)
	if err != nil {
		result.Message = response.Info_Error_OperationFailed
		result.Ret = response.Code_Error_OperationFailed
		this.Ctx.WriteString(result.FormatJsonString())
		return
	}

	defer session.Close()

	session.SetMode(mgo.Monotonic, true)

	fmt.Println("insert")
	c := session.DB(config.DataBaseName).C(config.DataTableUser)
	err = c.Insert(&user)
	if err != nil {
		result.Message = response.Info_Error_OperationFailed
		result.Ret = response.Code_Error_OperationFailed
		this.Ctx.WriteString(result.FormatJsonString())
		return
	}

	resultUser := models.User{}
	fmt.Println("query after insert")
	err = c.Find(&bson.M{"_id": user.Id}).One(&resultUser)

	fmt.Println("quer user: %v", resultUser)
	if err != nil {
		fmt.Println(error)
		result.Message = response.Info_Error_OperationFailed
		result.Ret = response.Code_Error_OperationFailed
		this.Ctx.WriteString(result.FormatJsonString())
		return
	}

	resultUser.Source = ""

	result.Message = response.Info_Success
	result.Ret = response.Code_Success
	result.Data = resultUser

	this.Ctx.WriteString(result.FormatJsonString())
}

func isUserExistsDB(openId string) (bool, models.User) {
	fmt.Println("isUserExistsDB")
	result := models.User{}
	session, err := mgo.Dial(config.DataBaseIP)
	if err != nil {
		fmt.Println("isUserExistsDB:%s", err)
		return false, result
	}

	defer session.Close()

	session.SetMode(mgo.Monotonic, true)
	c := session.DB(config.DataBaseName).C(config.DataTableUser)

	err = c.Find(bson.M{"uid": openId}).One(&result)
	if err != nil {
		return false, result
	}

	if strings.EqualFold(openId, result.Uid) {
		return true, result
	}

	return false, result
}

func (this *AuthController) Get() {
	this.Ctx.WriteString("auth get\n")
	sign := this.GetString("sign")
	this.Ctx.WriteString(sign)
}
